package io.renren.modules.iotp.utils;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 拼接接收到的消息
 * @author zhouxidong
 *
 */
public class Msg_rellect {
	
	/**
	 * 日志
	 */
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 存放收集到的byte[]信息
	 */
	private List<Byte> rellect_list = new ArrayList<>();
	
	/**
	 * 消息体的长度
	 */
	private Integer bodylength = 0;
	
	/**
	 * 需要拼接的byte数组
	 */
	private byte[] rellect_byte = null;
	
	/**
	 * rellect_byte的指针
	 */
	private int rellect_point = 0;
	
	/**
	 * 储存已经拼接好的byte数组
	 */
	private List<byte[]> result = new ArrayList<>();
	
	/**
	 * 是否可以向rellect_byte中复制数据
	 */
	private boolean enable = false;
	
	/**
	 * 拼接接收到的信息
	 * @param data
	 * @return
	 */
	public List<byte[]> rellect(byte[] data){
		// 检查是否满足拼接条件
		if(check_before()){
			linked(data);
			List<byte[]> list = new ArrayList<>();
			list.addAll(result);
			if(!list.isEmpty()){
				this.result.clear();
				return list;
			}
			return null;
		}else{
			return null;
		}
	}
	
	/**
	 * 检查是否满足拼接条件
	 * @return
	 */
	private boolean check_before(){
		if(this.bodylength <= 8192 && this.bodylength >=0){// 满足这个条件说明已经确定消息体长度，可以拼接
			return true;
		}else{ // 满足这个条件说明通讯出现了异常
			// 重新连接
			relink();
			// 初始化Msg_rellect
			init_Msg_rellect();
			return false;
		}
	}
	
	/**
	 * socket重连
	 */
	private void relink(){
//		Map<SocketBean,Msg_rellect> map = SocketUtils.RELLECTMESSAGE;
//		// 重新连接socket
//		for(SocketBean sb : map.keySet()){
//			if(map.get(sb) == this){
//				String address = sb.getServerip()+":"+sb.getServerport();
//				try {
//					logger.error("地址为：" + address +"的服务端出现异常，需要断开重连！！");
//					sb.getSocketChannel().close();
//					sb.getSelectionKey();
//					logger.error(address+"已经断开，正在重连");
//    				sb.setConnectstatus(2);
//    				sb.initialize();
//				} catch (IOException e) {
//					try {
//						sb.getSocketChannel().close();
//					} catch (IOException e1) {
//						logger.error("地址为：" + address +"的服务端断开出现异常！！");
//					}
//				}
//				// 跳出循环
//				break;
//			}
//		}
	}
	
	/**
	 * 初始化Msg_rellect
	 */
	private void init_Msg_rellect(){
		// 正常复位
		reset();
		this.rellect_list.clear();
		this.result.clear();
	}
	
	/**
	 * 正常复位
	 */
	private void reset(){
		this.enable = false;
		this.bodylength = 0;
		this.rellect_point = 0;
		this.rellect_byte = null;
	}
	
	/**
	 * 拼接传入的字节数组
	 * @param data
	 */
	private void linked(byte[] data){
		// 将传入的字节数组添加到this.rellect_list中
		for(Byte b : data){
			this.rellect_list.add(b);
		}
		// 循环拷贝数据
		while(rellect_list.size() > 160){
			cycle_copy();
		}
	}
	
	/**
	 * @author 周西栋
	 * @date 2018年6月21日
	 * @Title: cycle_copy
	 * @Description: 循环拷贝数据
	 * @param     参数
	 * @return void    返回类型
	 * @throws
	 */
	private void cycle_copy(){
		if(bodylength == 0){// 初始化或重新开始
			if(this.rellect_list.size() > 160){
				byte[] new_body_length = new byte[4];
				new_body_length[0] = this.rellect_list.get(156);
				new_body_length[1] = this.rellect_list.get(157);
				new_body_length[2] = this.rellect_list.get(158);
				new_body_length[3] = this.rellect_list.get(159);
				
				int length = Hex.byteArrayToIntDesc(new_body_length,4);
				if((length > 8192) || (length <= 0)){
					// 出现异常，重连
					relink();
					init_Msg_rellect();
				}else{// 满足条件，为this.bodylength赋值
					this.bodylength = length;
					// 创建需要接收的byte数组
					rellect_byte = new byte[160 + this.bodylength + 2];
					// 指针复位
					this.rellect_point = 0;
					// 改变可复制标记
					this.enable = true;
					// 将this.rellect_list中的
					copy_data();
				}
			}
		}else{
			// 将this.rellect_list中的
			copy_data();
		}
	}
	
	/**
	 * 将rellect_list里的数据转到rellect_byte中
	 */
	private void copy_data(){
		while(enable && rellect_list.size() > 0){
			this.rellect_byte[this.rellect_point] = this.rellect_list.get(0);
			this.rellect_list.remove(0);
			this.rellect_point++;
			if(this.rellect_point == rellect_byte.length){
				enable = false;
				// 先将数据转移
				byte[] copy = new byte[this.rellect_byte.length];
				for(int i = 0 ; i < copy.length; i++ ){
					copy[i] = this.rellect_byte[i];
				}
				// 当拼接完整后，将拼接完当放入this.result中
				this.result.add(copy);
				// 复位
				reset();
			}
		}
	}
	
}
